/**
  ******************************************************************************
  * @file    sysrtc.c
  * @brief   This file provides code for the configuration
  *          of the RTC instances.
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "bsp.h"

Sys_DataTimeType Sys_Runtime;
Sys_DataTimeType Sys_Adjtime;

/* RTC init function */
void SystemRTC_Config(void)
{
  LL_RTC_InitTypeDef RTC_InitStruct = {0};
  LL_RTC_TimeTypeDef RTC_TimeStruct = {0};
  LL_RTC_DateTypeDef RTC_DateStruct = {0};
  
  if(LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSE)
  {
    FlagStatus pwrclkchanged = RESET;
    /* Update LSE configuration in Backup Domain control register */
    /* Requires to enable write access to Backup Domain if necessary */
    if(LL_APB1_GRP1_IsEnabledClock (LL_APB1_GRP1_PERIPH_PWR) != 1U)
    {
      /* Enables the PWR Clock and Enables access to the backup domain */
      LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
      pwrclkchanged = SET;
    }
    
    if(LL_PWR_IsEnabledBkUpAccess () != 1U)
    {
      /* Enable write access to Backup domain */
      LL_PWR_EnableBkUpAccess();
      while (LL_PWR_IsEnabledBkUpAccess () == 0U)
      {
      }
    }
    
    LL_RCC_ForceBackupDomainReset();
    LL_RCC_ReleaseBackupDomainReset();
    LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_LOW);
    LL_RCC_LSE_Enable();
    
    /* Wait till LSE is ready */
    while(LL_RCC_LSE_IsReady() != 1)
    {
    }
    
    LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
    /* Restore clock configuration if changed */
    if (pwrclkchanged == SET)
    {
      LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_PWR);
    }
  }

  /* Peripheral clock enable */
  LL_RCC_EnableRTC();
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
  
  LL_PWR_EnableBkUpAccess();
  
  /* Initialize RTC and set the Time and Date */
  RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR;
  RTC_InitStruct.AsynchPrescaler = 127;
  RTC_InitStruct.SynchPrescaler = 255;
  LL_RTC_Init(RTC, &RTC_InitStruct);
  
  if(LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR0) != SYS_BKP_EFFECTIVE)
	{
		RTC_TimeStruct.TimeFormat = LL_RTC_TIME_FORMAT_AM_OR_24;
		RTC_TimeStruct.Hours = 0x16;
		RTC_TimeStruct.Minutes = 0x35;
		RTC_TimeStruct.Seconds = 0x00;
		LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BCD, &RTC_TimeStruct);
		
		RTC_DateStruct.WeekDay = LL_RTC_WEEKDAY_WEDNESDAY;
		RTC_DateStruct.Month = LL_RTC_MONTH_OCTOBER;
		RTC_DateStruct.Day = 0x13;
		RTC_DateStruct.Year = 0x21;
		LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BCD, &RTC_DateStruct);
		
		LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, SYS_BKP_EFFECTIVE);
	}
  
  LL_PWR_DisableBkUpAccess();
}

void Sys_GetDataTime(void)
{
	uint32_t date = 0, time = 0;
  
	date = LL_RTC_DATE_Get(RTC);
	time = LL_RTC_TIME_Get(RTC);

	Sys_Runtime.year   = __LL_RTC_CONVERT_BCD2BIN((uint8_t)(date & 0x000000FF));
	Sys_Runtime.month  = __LL_RTC_CONVERT_BCD2BIN((uint8_t)((date >> 8) & 0x000000FF));
	Sys_Runtime.day    = __LL_RTC_CONVERT_BCD2BIN((uint8_t)((date >> 16) & 0x000000FF));
	Sys_Runtime.second = __LL_RTC_CONVERT_BCD2BIN((uint8_t)(time & 0x000000FF));
	Sys_Runtime.minute = __LL_RTC_CONVERT_BCD2BIN((uint8_t)((time >> 8) & 0x000000FF));
	Sys_Runtime.hour   = __LL_RTC_CONVERT_BCD2BIN((uint8_t)((time >> 16) & 0x000000FF));
  Sys_Runtime.allmin = (Sys_Runtime.hour * 60) + Sys_Runtime.minute;
//	Sys_Runtime.allsec = (Sys_Runtime.allmin * 60) + Sys_Runtime.second;
}

void Sys_SetDataTime(void)
{
	LL_RTC_TimeTypeDef RTC_TimeStruct = {0};
	LL_RTC_DateTypeDef RTC_DateStruct = {0};
	LL_PWR_EnableBkUpAccess();
  
	RTC_TimeStruct.TimeFormat = LL_RTC_TIME_FORMAT_AM_OR_24;
	RTC_TimeStruct.Hours      = Sys_Adjtime.hour;
  RTC_TimeStruct.Minutes    = Sys_Adjtime.minute;
  RTC_TimeStruct.Seconds    = Sys_Adjtime.second;
  LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BIN, &RTC_TimeStruct);
	
  RTC_DateStruct.WeekDay = LL_RTC_WEEKDAY_FRIDAY;
	RTC_DateStruct.Month   = Sys_Adjtime.month;
  RTC_DateStruct.Day     = Sys_Adjtime.day;
  RTC_DateStruct.Year    = Sys_Adjtime.year;
  LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BIN, &RTC_DateStruct);
  
  LL_PWR_DisableBkUpAccess();
}
